import { AxiosError, type AxiosRequestConfig } from "axios";
import { merge } from "lodash-es";

import feedback from "../feedback";
import { HttpRequest } from "./http";
import type { AxiosHooks } from "./type";

/**
 * 全局拦截器的 hooks
 */
const axiosHooks: AxiosHooks = {
    requestInterceptorsHook(config) {
        // NProgress.start();
        const { withToken, isParamsToData } = config.requestOptions;
        const params = config.params || {};
        const headers = config.headers || {};

        // 添加token
        if (withToken) {
            // const token = cache.get(TOKEN_KEY);
            // headers.Authorization = `Bearer ${token}`;
            headers.Authorization = `Bearer xxx`;
        }
        // POST请求下，isParamsToData为true，并且无data，也就是请求体为空，则将查询字符串放到请求体中
        if (isParamsToData && !Reflect.has(config, "data") && config.method?.toUpperCase() === "POST") {
            config.data = params;
            config.params = {};
        }
        config.headers = headers;
        return config;
    },
    requestInterceptorsCatchHook(err) {
        // NProgress.done();
        return err;
    },
    async responseInterceptorsHook(response) {
        // NProgress.done();

        const { code, show, msg } = response.data;

        // 自定义的错误状态码范围，已启用
        if (code >= 1001) {
            msg && feedback.msgError(msg.toString());
            return Promise.reject();
        }
        switch (code) {
            case 200:
            case 201:
            case 1000: // 自定义的成功状态码，暂未启用
                if (show) msg && feedback.msgSuccess(msg.toString());
                console.log("response------");
                return response;
            case 400: // 以下错误代码处理为兼容 nest 默认的错误处理代码，比如 class-validator 参数验证失败，code 默认为 400
                msg && feedback.msgError(msg.toString());
                return Promise.reject(response);
            case 401:
                msg && feedback.msgError(msg.toString());
                // router.push(PageEnum.LOGIN).then(() => clearAuthInfo());
                return Promise.reject();
            case 403:
                msg && feedback.msgError(msg.toString());
                // router.push(PageEnum.ERROR_403);
                return Promise.reject();
            case 404:
                msg && feedback.msgError(msg.toString());
                return Promise.reject();
            case 500:
                msg && feedback.msgError(msg.toString());
                return Promise.reject();
            default:
                return response;
        }
        // switch (code) {
        //     case ResponseCodeEnum.SUCCESS:
        //         if (show) {
        //             msg && feedback.msgSuccess(msg.toString());
        //         }
        //         return data;
        //     case ResponseCodeEnum.FAIL:
        //         if (show) {
        //             msg && feedback.msgError(msg.toString());
        //         }
        //         return Promise.reject(data);
        //     case ResponseCodeEnum.LOGIN_FAILURE:
        //         clearAuthInfo();
        //         router.push(PageEnum.LOGIN);
        //         return Promise.reject();
        //     case ResponseCodeEnum.OPEN_NEW_PAGE:
        //         window.location.href = data.url;
        //         return data;
        //     case ResponseCodeEnum.NOT_INSTALL:
        //         window.location.replace("/install/install.php");
        //         break;
        //     default:
        //         return data;
        // }
    },
    responseInterceptorsCatchHook(error) {
        // NProgress.done();
        if (error.code !== AxiosError.ERR_CANCELED) {
            // 非取消请求导致的“错误”，进行错误提示
            error.message && feedback.msgError(error.message);
        }
    }
};

/**
 * 默认请求配置
 */
const defaultOptions: AxiosRequestConfig = {
    //接口超时时间
    timeout: 4000,
    // 基础接口地址
    // baseURL: "https://jsonplaceholder.typicode.com",
    baseURL: "http://localhost:3000/",
    //请求头
    // headers: { "Content-Type": "application/json;charset=UTF-8", version: 1 },
    // axios 拦截器的 hooks，默认配有全局拦截
    axiosHooks: axiosHooks,
    // 默认携带cookie
    withCredentials: false,
    // 调试模式
    debuger: false,
    // 每个接口可以单独配置
    requestOptions: {
        // 是否将params视为data参数，仅限post请求
        isParamsToData: false,
        //是否返回默认的响应
        isReturnNativeResponse: false,
        // 是否提取接口响应对象中的data字段返回。
        // 默认为不提取。如果全局设置提取，则最好去修改 axios 封装中 request 方法的返回值类型
        isExtractAPIDataField: false,
        // 接口拼接地址
        urlPrefix: "",
        // 是否携带token
        withToken: true,
        // 开启请求超时重新发起请求请求机制
        isOpenRetry: true,
        // 重新请求次数
        retryCount: 3,
        // 是否开启防抖请求，默认开启
        debounceRequest: false
    }
};

/**
 * 创建axios实例
 * @param opt axios请求配置
 * @returns  axios实例
 */
function createAxios(opt?: Partial<AxiosRequestConfig>) {
    return new HttpRequest(
        // 深度合并
        merge(defaultOptions, opt || {})
    );
}

export const request = createAxios();
